/*
 * CDDL HEADER START
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at
 * http://www.sun.com/cddl/cddl.html and legal/CDDLv1.0.txt
 * See the License for the specific language governing
 * permission and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright 2007 Sun Microsystems Inc. All Rights Reserved
 * CDDL HEADER END
 */

package cn.collin.commons.codec;

import java.io.UnsupportedEncodingException;

/**
 * idea from com.sun.portal.desktop.encode
 * 
 * This class contains some utility methods for encoding and decoding cookie
 * value so that they may be safely write to client.
 * 
 * @author collin.code@gmail.com
 * 
 */
public class CookieEncoderDecoder {
	/**
	 * special characters that need to be escaped when setting cookie value.
	 */
	public static final char[] cookieEscapeChars = { ';', ',', ' ', '[', ']',
			'{', '}', '=', '"', '/', '\\', '?', '@', ':', '\n', '\r' };

	/**
	 * Checks for special characters that cannot be used as a cookie value
	 */
	private static boolean isCookieEscChar(char ch) {
		boolean result = false;
		for (int i = 0; i < cookieEscapeChars.length; i++) {
			if (ch == cookieEscapeChars[i]) {
				result = true;
				break;
			}
		}
		return result;
	}

	/**
	 * Encodes a string to be used for a cookie value. Translates any special
	 * characters defined in the static arrays cookieEscapeChars and encodes the
	 * special characters using the following algorithm:
	 * 
	 * The algorithm translates, for example, ',' the comma character into '%2c'
	 * where 2c is the hex equivalent of the comma character's numeric value.
	 * 
	 */
	public String encode(String value) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < value.length(); i++) {
			char ch = value.charAt(i);
			if (isCookieEscChar(ch)) {
				int j = (int) ch;
				buf.append("%").append(Integer.toHexString(j));
			} else {
				buf.append(ch);
			}
		}
		return buf.toString();
	}

	/**
	 * Decodes a cookie cncoded string. A cookie encoded string is one that has
	 * had special characters excaped as %XY where XY is the hex equivalent of
	 * the character's numeric value. The specific characters to be escaped are
	 * contained in the static array cookieEscapeChars.
	 * 
	 * This method calls java.net.URLDecoder to decode the string. A URL encoded
	 * string is of the same format as a cookie encoded one, with different
	 * escape characters. The implementation of URLDecoder.decode() simply
	 * translates all %SY into the character equivalent, not paying special
	 * attention to whether the character represents something that would have
	 * been URL encoded. The implementation here is therefore dependent upon the
	 * implementation of java.net.URLDecoder and may need to be changed as the
	 * JDK implementation changes.
	 * 
	 */
	public String decode(String value) {
		try {
			return java.net.URLDecoder.decode(value, "UTF-8");
		} catch (UnsupportedEncodingException uee) {
			throw new IllegalStateException(uee);
		}
	}
}
